package org.transfer.utils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * Created by vdi052 on 2019/1/10.
 */
public class MysqlInfo {
	/**
	 * 分析数据文件 获取原数据名 如有多个文件则区分 数据结构文件和数据文件
	 * 
	 * @param path
	 * @return
	 * @throws Exception
	 */
	public static Map<String, Object> getInfo(String path) {
		Map<String, Object> map = new HashMap<>();
		String name = "";
		String dbName = "";
		String dbName1 = "";
		String dbName2 = "";
		String filepathtemp = "";
		/*
		 * flag 1 代表 先判断的数据结构文件 或者 是结构与数据结合的文件 2代表 先判断的 数据文件
		 * 从而决定传入文件在resultList集合里的顺序 进而影响了恢复过程中 文件的先后恢复顺序
		 */
		int flag = 0;
		// 传入文件地址集合
		List<String> filepaths = new ArrayList<>();
		// 要返回的list集合
		List<String> resultList = new ArrayList<>();
		// b 是多文件中分析出的原库名是否一致标志
		boolean b = false;
		InputStreamReader isr = null;
		BufferedReader br = null;
		try {
			filepaths = Arrays.asList(path.split(","));
			// 判断文件数量
			if (filepaths != null && filepaths.size() > 0 && filepaths.size() <= 2) {
				for (int i = 0; i < filepaths.size(); i++) {
					filepathtemp = filepaths.get(i);
					// 获取文件字符集信息 防止乱码
					String encoding = EncodingDetect.getJavaEncode(filepathtemp);
					// 从工具类中获取日志信息
					isr = new InputStreamReader(new FileInputStream(filepathtemp), encoding);
					br = new BufferedReader(isr);
					String line = null;
					Matcher matcher = null;
					while ((line = br.readLine()) != null) {
						if (line.contains("CREATE TABLE")) {
							if (!resultList.contains(filepathtemp)) {
								resultList.add(filepathtemp);
								if (flag == 0) {
									flag = 1;
								}
							}
						} else if (line.contains("INSERT INTO ") || line.contains("insert  into")) {
							if (filepaths.size() > 1) {
								if (!resultList.contains(filepathtemp)) {
									resultList.add(filepathtemp);
									if (flag == 0) {
										flag = 2;
									}
								}
							}
						}
						if (line.contains("Source Schema")) {
							matcher = getMatcher(line, "Source Schema\\s*?:\\s*? (.*?)$");
							while (matcher.find()) {
								dbName = matcher.group(1);
							}
						} else if (line.contains("Database:") && line.contains("Host:")) {
							matcher = getMatcher(line, "Database:(.*?)$");
							while (matcher.find()) {
								dbName = matcher.group(1);
							}
						} else if (line.contains("Database - ") && line.contains("MySQL -")) {
							matcher = getMatcher(line, "Database - (.*?)$");
							while (matcher.find()) {
								dbName = matcher.group(1);
							}
						}
						if (!"".equals(dbName)) {
							if (i == 0) {
								dbName1 = dbName;
							} else if (i == 1) {
								dbName2 = dbName;
							}
						}
					}
					if (!"".equals(dbName1)) {
						if (filepaths.size() == 2) {
							if (dbName1.equals(dbName2)) {
								b = true;
							}
						} else if (filepaths.size() == 1) {
							b = true;
						}
						dbName = dbName1;
					}
				}
			} else {
				throw new IOException();
			}
		} catch (IOException e) {
			name = "日志文件地址有误!";
			throw new RuntimeException(name);
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (isr != null) {
				try {
					isr.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		if (!"".equals(dbName)) {
			dbName = dbName.replace(" ", "");
		}
		if (flag == 2) {
			Collections.reverse(resultList);
		}
		map.put("dbName", dbName);
		map.put("result", b);
		map.put("list", resultList);
		return map;
	}

	private static Matcher getMatcher(String line, String regex) {
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(line);
		return matcher;
	}

	/**
	 * 过滤sql文件中的建库语句 及 切换数据库语句
	 * 
	 * @param filepath
	 * @param logPath
	 */
	public static void getsql(String filepath, String logPath) {
		BufferedReader br = null;
		InputStreamReader isr = null;
		StringBuffer temp = new StringBuffer();
		BufferedWriter bufferedWriter = null;
		OutputStreamWriter writerStream = null;
		FileOutputStream fileOutputStream = null;
		FileInputStream fileInputStream = null;
		String encoding = "";
		try {
			fileInputStream = new FileInputStream(filepath);
			fileOutputStream = new FileOutputStream(logPath);
			encoding = EncodingDetect.getJavaEncode(filepath);
			isr = new InputStreamReader(fileInputStream, encoding);
			br = new BufferedReader(isr);
			String line = null;
			while ((line = br.readLine()) != null) {
				if (line.contains("CREATE DATABASE")) {
					continue;
				} else if (line.contains("USE `")) {
					continue;
				} else {
					temp.append(line + System.lineSeparator());
				}
			}
			writerStream = new OutputStreamWriter(fileOutputStream, encoding);
			bufferedWriter = new BufferedWriter(writerStream);
			bufferedWriter.write(temp.toString());
		} catch (IOException e) {
			String name = "解析sql文件失败!";
			throw new RuntimeException(name);
		} finally {
			try {
				if (bufferedWriter != null) {
					bufferedWriter.flush();
				}
				if (writerStream != null) {
					writerStream.flush();
				}
				if (fileOutputStream != null) {
					fileOutputStream.flush();
				}
				if (bufferedWriter != null) {
					bufferedWriter.close();
				}
				if (writerStream != null) {
					writerStream.close();
				}
				if (br != null) {
					br.close();
				}
				if (isr != null) {
					isr.close();
				}
				if (fileOutputStream != null) {
					fileOutputStream.close();
				}
				if (fileInputStream != null) {
					fileInputStream.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}

	public static Process cmd(String commandBuf) {
		Process process = null;
		try {
			// 执行命令
			process = Runtime.getRuntime().exec(commandBuf);
			process.waitFor();
		} catch (Exception e) {
			String name = "执行cmd命令时出错!";
			throw new RuntimeException(name);
		}
		return process;
	}
}
